#include <iostream>
#include <assert.h>
using namespace std;

// void Swap(int& a, int& b)
// void SLTPushBack(SLTNode*& phead, int x)
// int main()
//{
//	int a = 0;
//	int& b = a;
//	a++;
//	b++;
//
//	int x = 0;
//	int y = 1;
//
//	return 0;
//}

// int main()
//{
//	int a = 0;
//
//	// 引用必须初始化
//	// int& b;
//
//	int& c = a;
//	int d = 1;
//
//	// c变成d的别名？还是d赋值给c？  ----后者
//	c = d;
//
//	// 一个对象可以有多个别名，可以别名继续取别名
//	int& e = a;
//	int& f = e;
//
//	return 0;
// }

// 多个对象不能用同一个别名
// int main()
//{
//	int a = 0;
//	int b = 1;
//	int& c = a;
//	c = b;
//
//	return 0;
// }

// 效率对比
// #include <time.h>
// struct A {
//	int a[10000];
// };
////不同的域里面可以有同名变量，这里也可以用aa
// void TestFunc1(A aa) {}
//
// void TestFunc2(A& aa) {}
//
// void TestRefAndValue()
//{
//	A a;
//	// 以值作为函数参数
//	size_t begin1 = clock();
//	for (size_t i = 0; i < 10000; ++i)
//		TestFunc1(a);
//	size_t end1 = clock();
//
//	// 以引用作为函数参数
//	size_t begin2 = clock();
//	for (size_t i = 0; i < 10000; ++i)
//		TestFunc2(a);
//	size_t end2 = clock();
//
//	// 分别计算两个函数运行结束后的时间
//	//引用更快
//	cout << "TestFunc1(A)-time:" << end1 - begin1 << endl;
//	cout << "TestFunc2(A&)-time:" << end2 - begin2 << endl;
// }

//									效率对比,引用返回更快
// A a;
//// 值返回
// A TestFunc1() { return a; }
//// 引用返回
// A& TestFunc2() { return a; }
//
// void TestReturnByRefOrValue()
//{
//	// 以值作为函数的返回值类型
//	size_t begin1 = clock();
//	for (size_t i = 0; i < 100000; ++i)
//		TestFunc1();
//	size_t end1 = clock();
//
//	// 以引用作为函数的返回值类型
//	size_t begin2 = clock();
//	for (size_t i = 0; i < 100000; ++i)
//		TestFunc2();
//	size_t end2 = clock();
//
//	// 计算两个函数运算完成之后的时间
//	cout << "TestFunc1 time:" << end1 - begin1 << endl;
//	cout << "TestFunc2 time:" << end2 - begin2 << endl;
// }
//
// int main()
//{
//	//TestRefAndValue();
//	TestReturnByRefOrValue();
//
//	return 0;
// }

//						//引用做返回值

// int& Count()
//{
//	int n = 0;
//	n++;
//
//	return n;
// }
// int main()
//{
//	int ret = Count();
//	cout << ret << endl;
//
//	cout << ret << endl;
//
//	return 0;
// }

// int& Count()
//{
//	int n = 0;
//	n++;
//
//	return n;
// }
//
// int main()
//{
//	int& ret = Count();
//	cout << ret << endl;
//	cout << ret << endl;
//	cout << ret << endl;
//	Count();
//	cout << ret << endl;
//
//	return 0;
// }

// 这个C++程序试图返回一个局部变量的引用，这是不允许的，因为局部变量在函数返回后就会被销毁，它们所占用的内存空间会被释放。任何试图访问已经销毁的局部变量的行为都是未定义的（undefined behavior），这意味着程序可能会崩溃，或者返回任何随机的值，或者产生其他不可预测的结果。
//
// 在你的Count函数中，你创建了一个局部变量n，初始化为0，然后将其加1，并试图返回它的引用。然而，当Count函数返回时，局部变量n的存储空间就不再有效了。因此，任何尝试访问n的引用都是错误的。
//
// 在你的main函数中，你试图捕获这个返回的引用并将其存储在ret中。然而，因为n已经被销毁，ret实际上是一个悬垂引用（dangling reference），它指向的内存可能已经被其他变量或数据覆盖。
//
// 接下来，你试图打印ret的值三次。由于ret是一个悬垂引用，每次打印它都可能得到不同的结果，因为那块内存可能已经被其他操作改变了。然而，由于未定义行为的具体表现取决于许多因素（包括编译器优化、内存布局等），你甚至可能每次运行程序都得到相同的结果，但这并不意味着你的程序是正确的。
//

// 出了函数作用域，返回对象就销毁了，不能用引用返回，否则结果是不确定
// int& Add(int a, int b)
//{
//	int c = a + b;
//	return c;
//}
//
// int main()
//{
//
//	int& ret = Add(1, 2);
//	cout << "Add(1, 2) is :" << ret << endl;
//
//	Add(3, 4);//没有赋值给ret
//
//	cout << "Add(1, 2) is :" << ret << endl;
//	return 0;
//}

// void func()
//{
//	int c = 0;
//	cout << &c << endl;
// }
// void func2()
//{
//	int a = 0;
//	cout << &a << endl;
// }
// int main()
//{
//	//func();
//	//func();
//	func();
//	func2();//两个函数都是用的同一块空间。
//	return 0;
// }

// int& Add(int a, int b)
//{
//	//static int c = a + b;  //c此时在静态区，add销毁不影响c
//	//静态局部变量的初始化只能发生在程序开始运行时，而不是在每次函数调用时
//	//第二次c 的值并没有改变，因为它已经在第一次调用时被初始化了，并且之后不会再次初始化。
//	//两次结果都是3
//
//
//	static int c;
//	c = a + b;
//	//c 会在每次调用 Add 函数时被重新赋值
//	//这样就是 3 7
//
//
//	return c;
// }
// int main()
//{
//	int& ret = Add(1, 2);
//
//	cout << "Add(1, 2) is :" << ret << endl;
//	Add(3, 4);
//	cout << "Add(1, 2) is :" << ret << endl;
//	return 0;
// }

// 出了作用域 还在 才能引用返回

// int main()
//{
//	int& ret = Add(1, 2);
//	cout << "Add(1, 2) is :" << ret << endl;
//
//	Add(3, 4);
//
//	cout << "Add(1, 2) is :" << ret << endl;
//	return 0;
// }

// void func1()
//{
//	int c = 0;
//	cout << &c << endl;
// }
//
// void func2()
//{
//	int a = 0;
//	cout << &a << endl;
// }
//
// int main()
//{
//	/*func();
//
//	func();*/
//
//	func1();
//
//	func2();
//
//	return 0;
// }

// typedef struct SeqList
//{
//	int a[100];
//	int size;
// }SL;
//
// void SLModify(SL* ps, int pos, int x)
//{
//	//...
//	assert(ps);
//	assert(pos < ps->size);
//	ps->a[pos] = x;
// }
//
//  //引用做返回值：可以修改返回对象
// int& SLat(SL* ps, int pos)
//{
//	assert(ps);
//	assert(pos < ps->size);
//
//	return ps->a[pos];
// }
////没有 int 后面的引用符号的话，传的只是ps->a[pos] 的这个值的拷贝，不会修改这个值
////引用后返回的是别名
// int main()
//{
//	SL s;
//	//...
//
//	SLat(&s, 3) = 10;
//
//	// 每个位置的值++
//	for (size_t i = 0; i < s.size; i++)
//	{
//		SLat(&s, i)++;
//	}
//
//	return 0;
// }

// 使用引用作为返回值是安全的，只要满足以下条件：
// 引用的对象必须在函数返回后仍然存在：这是最重要的条件。如果返回的是局部变量的引用，那么当函数返回后，局部变量会被销毁，引用就会变成一个悬垂引用（dangling reference），
// 这会导致未定义行为。在你的例子中，SLat 返回的是 ps->a[pos] 的引用，而 ps 是一个指向有效对象的指针，因此 ps->a[pos] 在函数返回后仍然存在，所以这是安全的。
// 不返回非常量对象的常量引用：这通常是一个好的编程实践，以避免意外地修改本不应被修改的对象。但在你的例子中，你返回的是一个非常量引用，
// 因此调用者可以修改被返回的对象，这是符合你的函数设计目的的。
// 避免返回指向动态分配内存的引用：如果返回的是指向通过 new 或 malloc 等函数动态分配的内存的引用，那么调用者必须负
// 责在适当的时候释放这块内存，否则会造成内存泄漏。在你的例子中，你没有使用动态内存分配，所以这不是一个问题。

///////////////////////////////////////////////////////////////////////
// 常引用
// int main()
//{
//	// 取别名，权限不能放大
//	const int a = 10;
//	//int& b = a; //不行
//	//int b = a;  //可以
//	const int& b = a;//可以
//
//
//	// 权限可以缩小
//	int c = 20;
//	const int& d = c;
//	const int& e = 10;//也可以给常量取别名，不加const不行！ 10是常量
//
//	int i = 1;
//	double j = i;//可以，涉及类型转换
//	double& rj = i;//不行
//	const  double& rj = i;//可以
//	//rj解引用的是i的那个临时变量，临时变量具有常性，所以加了const就可以了
//
//
//
//	return 0;
//}
// 无论隐式类型转换和强制类型转换的时候会产生临时变量
// i 是一个整数类型的变量，而 j 是一个浮点数类型的变量。当进行隐式类型转换时，C++会创建一个临时变量来存储转换后的值，然后将临时变量的值赋给目标变量 j

// 引用和指针的区别

//
// int main()
//{
//	//int a = 10;
//
//	//// 语法，b是否开空间了——没有
//	//int& b = a;
//
//	//// 语法，ptr开了空间
//	//int* ptr = &a;
//
//	char ch = 'x';
//	char& r = ch;
//	cout << sizeof(r) << endl;
//	return 0;
//}

#define ADD(x, y) ((x) + (y))

////////////////////////////////---------------宏:单纯的是一种替换
// 错误写法：
// #define ADD(int x, int y) return x + y;
// #define ADD(x, y) return x + y;
// #define ADD(x, y) x + y;
// #define ADD(x, y) (x + y)
// #define ADD(x, y) (x) + (y)
// #define ADD(x, y) ((x) + (y));

// 正确写法：
#define ADD(x, y) ((x) + (y)) // 不能加分号

// 宏的缺点
// 1、容易出错，语法细节多
// 2、不能调试
// 3、没有类型安全的检查

// int main()
//{
//	// 写好了，建议替换看看
//	int ret1 = ADD(2, 3)*5; // （(2)+(3))*5
//
//	int a = 1, b = 2;
//	//int ret2 = ADD(a | b, a & b); // ((a | b) + (a & b))
//	//int ret2 = ((a | b) + (a & b));
//
//	return 0;
// }

// enum const inline 替代宏
// enum const -> 宏常量
// inline ->宏函数

//					内联函数的优点：
// 可以调试
// 效率高，会展开
// 好写，语法简单
//

//
// inline int Add(int x, int y)
//{
//	int c = x + y;
//	return c;
//}
//
// int main()
//{
//	int ret1 = Add(1, 2);
//
//	// 优点：不用建立栈帧，提高效率
//	int ret2 = ADD(1, 2);
//
//	return 0;
//}

// inline int Add(int x, int y)
//{
//	int c = x + y;
//	int c1 = x + y;
//	int c2 = x + y;
//	int c3 = x + y;
//	int c4 = x + y;
//	int c5 = x + y;
//	int c6 = x + y;
//	int c7 = x + y;
//	int c8 = x + y;
//	int c9 = x + y*c8;
//	int c10 = x + y;
//	int c11 = x + y;
//	return c1+c10-c9;
// }
//
// int main()
//{
//	int ret1 = Add(1, 2);
//	int ret3 = Add(1, 2);
//
//
//	// 优点：不用建立栈帧，提高效率
//	int ret2 = ADD(1, 2);
//
//	return 0;
// }

//						auto关键字
// #include<typeinfo>
// int main()
//{
//	int a = 0;
//	int b = a;
//	auto c = a;
//	auto d = &a;
//	auto* e = &a;
//
//	cout << typeid(int) << endl;
//	cout << typeid(d).name() << endl;
//	cout << typeid(e).name() << endl;
//}

//						typeid用法
#include <iostream>
#include <typeinfo>
using namespace std;
// int main() {
//     int x = 10;
//     cout << "Type of x is: " << typeid(x).name() << endl;
//     double y = 3.14;
//     cout << "Type of y is: " << typeid(y).name() << endl;
//     const char* z = "Hello, World!";
//     cout << "Type of z is: " << typeid(*z).name() << endl;
//     // 注意这里使用 *z 来获取字符的类型，而不是指针的类型
//     return 0;
//     //Type of x is : int
//     //Type of y is : double
//     //Type of z is : char
// }

// #include <iostream>
// #include <typeinfo>
// using namespace std;
// int main() {
//     cout << "Type of int is: " << typeid(int).name() << endl;
//     cout << "Type of double is: " << typeid(double).name() << endl;
//     cout << "Type of const char* is: " << typeid(const char*).name() << endl;
////打印结果：
//    //Type of int is : int
//    //Type of double is : double
//    //Type of const char* is : char const* __ptr64
//  /*  __ptr64就是用来明确表明这是一个64位指针的
//    这里的__ptr64是一个编译器特定的修饰符，它通常出现在Microsoft Visual C++编译器生成的代码中，用于指示指针的大小。*/
//    return 0;
//}

#include <vector>
#include <string>

// void func(auto e)
//{
//
// }
//
// auto func(auto e)
//{
//
//
// }
// 不能做函数参数,也不能做返回值

// auto真正价值
// int main()
//{
//	vector<string> v;
////	vector<string>::iterator it = v.begin();
//	//auto自动推导出类型，可以短一点
//	auto it                     = v.begin();
////	auto x;//错的，必须初始化，要不然不知道什么类型
//
//
//}

//						9. 基于范围的for循环(C++11)

// int main()
//{
//	int array[] = { 1, 2, 3, 4, 5 };
//	//修改
//	for (int i = 0; i < sizeof(array) / sizeof(array[0]); ++i)
//		array[i] *= 2;
//	//遍历
//	for (int* p = array; p < array + sizeof(array) / sizeof(array[0]); ++p)
//		cout << *p << endl;
//
//	//for (int e : array)  //对数组里的数的拷贝
//	for (auto& e : array)//想要++  必须要加引用
//	{//这里只能用引用
//		e++;
//		cout << e << " ";
//	}
//	cout << endl;
//
//
//
//	// 依次取数组中数组赋值给e
//	// 自动判断结束，自动++往后走
//	for (auto e : array)
//	{
//		//也可以用int e ：array
//		//不过一般用auto，因为假如数组类型变了，auto可以自动识别
//		cout << e << " ";
//	}
//	cout << endl;
//
//	return 0;
// }

// 不能这样用，这里传的不是数组，是首元素的地址，是指针
// 要传数组名才行
// void TestFor(int array[])
//{
//	for (auto& e : array)
//		cout << e << endl;
// }

////////////////////////////////////////////////////////////////10. 指针空值nullptr(C++11)

// void f(int)
//{
//	cout << "f(int)" << endl;
// }
//
// void f(int*)
//{
//	cout << "f(int*)" << endl;
// }
//
// int main()
//{
//	//int* ptr = NULL;
//	int* ptr = nullptr;
//
//	f(0);
//	//f(NULL);
//	f(nullptr);
//
//	return 0;
// }

// void TestFor()
//{
//	int array[] = { 1,2,3,4,7,8,9 };
//	for (auto& e : array)
//	{
//		e *= 2;
//	}
//	for (auto& e : array)
//	{
//		cout << e << endl;
//	}
// }
// int main()
//{
//	TestFor();
//	return 0;
// }
